# Booking Service

В коде представлен прототип сервиса бронирования номеров в отелях, в котором реализована возможность забронировать свободный номер в отеле.

Сервис будет развиваться, например:
- появится отправка письма-подтверждения о бронировании
- появятся скидки, промокоды, программы лояльности
- появится возможность бронирования нескольких номеров

## Задание

Провести рефакторинг структуры и кода приложения, исправить существующие проблемы в логике. Персистентное хранение реализовывать не требуется, все данные храним в памяти сервиса.

В результате выполнения задания ожидается структурированный код сервиса, с корректно работающей логикой сценариев бронирования номеров в отелях.

### Чеклист:
- Код реорганизован и выделены слои
- Выделены абстракции и интерфейсы
- Технические и логические ошибки исправлены

### Ограничения:
- Реализация должна управлять состоянием в памяти приложения, но быть легко заменимой на внешнее хранилище
- Если у вас есть опыт с Go: используйте только стандартную библиотеку Go + роутер (например chi)
- Если у вас нет опыта с Go: можно реализовать решение на своем любимом стеке технологий

## Что будет на встрече

На встрече ожидаем, что вы продемонстрируете экран и презентуете свое решение: расскажете, какими проблемами обладает исходный код и как они решены в вашем варианте. Мы будем задавать вопросы о том, почему было решено разделить ответственность между компонентами тем или иным образом, какими принципами вы при этом руководствовались. Спросим, что будет, если продакт решит добавить какую-то новую фичу — как она ляжет на предложенную вами структуру. Также можем поговорить о более технических вещах: о значениях и указателях, многопоточности, интерфейсах, каналах.

## Например

Запуск:
```sh
go run ./cmd/booking-service/main.go
```

Отправка запроса:
```sh
curl --location --request POST 'localhost:8080/orders' \
--header 'Content-Type: application/json' \
--data-raw '{
    "hotel_id": "reddison",
    "room_id": "lux",
    "email": "guest@mail.ru",
    "from": "2024-01-02T00:00:00Z",
    "to": "2024-01-04T00:00:00Z"
}'
```

Запуск тестов:
```sh
go test ./...
```

## Основные изменения и улучшения

1. **Разделение на слои (Layered Architecture)**:
	- Проект разделен на разные слои: модели, хранилище, сервисы и обработчики. Это помогает разделить ответственность и облегчает сопровождение и тестирование кода.
2. **Использование интерфейсов**:
	- Определены интерфейсы для хранилищ заказов и доступности номеров. Это упрощает замену реализации хранилища (например, на базу данных) без изменения бизнес-логики.
3. **Тестирование**:
	- Написаны тесты для различных компонентов системы: обработчиков, сервисов и хранилищ. Это помогает гарантировать корректность работы системы и упрощает рефакторинг.
4. **Инициализация данных**:
	- Добавлена функция инициализации данных о доступности номеров в main.go, чтобы гарантировать корректное тестирование и работу сервиса.

### Дополнительные улучшения

1. **Логирование**:
	- Добавлено централизованное логирование с использованием стандартной библиотеки logrus для улучшения мониторинга и отладки.
2. **Управление зависимостями**:
	- Использовано внедрение зависимостей (Dependency Injection) для управления зависимостями компонентов, что упрощает тестирование и замену зависимостей.

### Возможности для дальнейшего улучшения

1. **Документация API**:
	- Можно использовать Swagger для автоматической генерации документации для REST API.
2. **Метрики и мониторинг**:
	- Можно добавить сбор метрик и мониторинг для сервиса с помощью Prometheus и Grafana для отслеживания состояния и производительности системы.

## Деплой через Kubernetes

Для деплоя приложения использовались манифесты Kubernetes, включающие Deployment и Service.

### Применение манифестов

```sh
kubectl apply -f deployments/configmap.yaml
kubectl apply -f deployments/deployment.yaml
kubectl apply -f deployments/service.yaml
```

### Доступ к сервису

После деплоя сервис доступен через команду `kubectl port-forward`:

```sh
kubectl port-forward svc/booking-service 8080:80
```

## Использование Skaffold для автоматизации

```sh
skaffold dev
```

Skaffold будет автоматически отслеживать изменения в коде, пересобирать образ и обновлять ваше приложение в Kubernetes.

### Соответствие требованиям задания

#### 1. Код реорганизован и выделены слои
Проект разделен на несколько слоев:
- **Models**: Содержит определения структур данных (моделей).
- **Storage**: Реализует интерфейсы и in-memory хранилища.
- **Services**: Содержит бизнес-логику.
- **Handlers**: Содержит HTTP-обработчики.
- **Cmd**: Содержит точку входа в приложение.

#### 2. Выделены абстракции и интерфейсы
Определены интерфейсы для абстрагирования работы с хранилищами:
- `OrderStorage`
- `RoomAvailabilityStorage`

#### 3. Технические и логические ошибки исправлены
Исправлены несколько логических и технических ошибок:
- Логическое управление состоянием доступности номеров.
- Обработка ошибок и валидация данных.
- Безопасность многопоточного доступа к данным с использованием мьютексов.

### Ограничения

#### 1. Реализация, которая управляет состоянием в памяти приложения, но которую легко заменить на внешнее хранилище
Использование интерфейсов для хранилищ позволяет легко заменить in-memory реализацию на внешнее хранилище, такое как база данных.

#### 2. Использование стандартной библиотеки Go и роутера (например, chi)
Мы использовали стандартную библиотеку Go. Вместо chi мы использовали стандартный `http.ServeMux`.

### Что будет на встрече

1. **Проблемы исходного кода**:
	- Плохая структура кода.
	- Отсутствие слоев абстракции.
	- Логические ошибки в обработке данных.

2. **Решение**:
	- Мы разделили код на слои, улучшили структуру.
	- Ввели интерфейсы для абстрагирования хранилищ.
	- Исправили ошибки в логике бронирования.

3. **Разделение ответственности**:
	- Модели для определения данных.
	- Хранилища для управления состоянием.
	- Сервисы для бизнес-логики.
	- Обработчики для работы с HTTP-запросами.

4. **Добавление новой функциональности**:
	- Легко добавить новые функции, такие как отправка подтверждений по электронной почте или программы лояльности, расширяя существующие сервисы или добавляя новые.

5. **Технические аспекты**:
	- Значения и указатели: объяснение, когда и почему использованы.

    - Многопоточность: безопасный доступ к данным с помощью мьютексов.
    - Интерфейсы и каналы: использование интерфейсов для абстрагирования хранилищ, при необходимости можно использовать каналы для общения между компонентами.
